package cc.cix.gt.org.service.impl;

import cc.cix.gt.common.entity.DeptTree;
import cc.cix.gt.common.entity.ResultPage;
import cc.cix.gt.common.entity.Tree;
import cc.cix.gt.common.util.SortUtil;
import cc.cix.gt.common.util.TreeUtil;
import cc.cix.gt.org.dto.query.QueryDeptReq;
import cc.cix.gt.org.entity.Dept;
import cc.cix.gt.org.entity.UserDataPermission;
import cc.cix.gt.org.mapper.DeptMapper;
import cc.cix.gt.org.service.IDeptService;
import cc.cix.gt.org.service.IUserDataPermissionService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author cix
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept>
        implements IDeptService {

    private final IUserDataPermissionService userDataPermissionService;

    @Override
    public ResultPage<Tree<Dept>> listDeptTree(QueryDeptReq dto) {
        try {
            List<Dept> depts = listDept(dto);
            List<DeptTree> trees = new ArrayList<>();
            buildTrees(trees, depts);
            List<Tree<Dept>> deptTree = (List<Tree<Dept>>) TreeUtil.build(trees);
            return new ResultPage<Tree<Dept>>().setRows(deptTree).setTotal((long) depts.size());
        } catch (Exception e) {
            log.error("获取部门列表失败", e);
        }

        return new ResultPage<>();
    }

    @Override
    public List<Dept> listDept(QueryDeptReq dto) {
        Dept dept = BeanUtil.toBean(dto, Dept.class);
        QueryWrapper<Dept> qw = new QueryWrapper<>(dept);
        SortUtil.handleWrapperSort(dto, qw);
        return list(qw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createDept(Dept dept) {
        if (ObjectUtil.isNull(dept.getParentId())) {
            dept.setParentId(Dept.TOP_DEPT_ID);
        }

        save(dept);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDept(Dept dept) {
        if (ObjectUtil.isNull(dept.getParentId())) {
            dept.setParentId(Dept.TOP_DEPT_ID);
        }

        updateById(dept);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDeptByIds(List<String> deptIds) {
        deleteDeptById(deptIds);
    }

    private void buildTrees(List<DeptTree> trees, List<Dept> depts) {
        depts.forEach(dept -> {
            DeptTree tree = new DeptTree();
            tree.setId(dept.getId());
            tree.setParentId(dept.getParentId());
            tree.setDeptName(dept.getDeptName());
            tree.setOrderNum(dept.getOrderNum());
            tree.setCreateTime(dept.getCreateTime());
            trees.add(tree);
        });
    }

    private void deleteDeptById(List<String> deptIds) {
        removeByIds(deptIds);
        userDataPermissionService.lambdaUpdate()
                .in(UserDataPermission::getDeptId, deptIds).remove();
        List<Dept> depts = lambdaQuery().in(Dept::getParentId, deptIds).list();
        if (CollectionUtils.isNotEmpty(depts)) {
            List<String> deptIdList = new ArrayList<>();
            depts.forEach(dept -> deptIdList.add(String.valueOf(dept.getId())));
            deleteDeptById(deptIdList);
        }
    }

}
